import axios from "axios";
import type {
  AxiosRequestConfig,
  InternalAxiosRequestConfig,
  AxiosResponse,
} from "axios";
import qs from "qs";
import { showConfirmDialog, showNotify } from "vant";
import { getToken, removeToken } from "./auth";

// 是否已经提示重新登录
let reloginPrompted = false;

axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";

/**
 * 参数处理
 * @param {*} params  参数
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function toUrlParams(params: Record<string, any>) {
  let result = "";
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    const part = encodeURIComponent(propName) + "=";
    if (Array.isArray(value)) {
      value.forEach((_val) => {
        if (_val !== null && _val !== "" && typeof _val !== "undefined") {
          const params = propName;
          const subPart = encodeURIComponent(params) + "=";
          result += subPart + encodeURIComponent(_val) + "&";
        }
      });
    } else if (typeof value == "object") {
      if (value instanceof Date) {
        result += part + value.toISOString() + "&";
      } else if (value != null) {
        console.error("通过URL参数发送数据时，属性类型不合法：", value);
      }
    } else if (["string", "number", "boolean"].includes(typeof value)) {
      result += part + encodeURIComponent(value) + "&";
    } else if (value) {
      console.error("通过URL参数发送数据时，属性类型不合法：", value);
    }
  }
  return result;
}

const commonConfig: AxiosRequestConfig = {
  // axios中请求配置有baseURL选项，表示请求URL公共部分
  baseURL: import.meta.env.VITE_BASE_API,
  transformRequest: [
    function (data, headers) {
      // 对 data 进行任意转换处理
      const contentType =
        headers["Content-Type"] ||
        headers["content-type"] ||
        headers["contentType"];
      if ("application/x-www-form-urlencoded" == contentType) {
        if (Array.isArray(data)) {
          throw '"数组"类型的数据无法以"application/x-www-form-urlencoded"的ContentType发送';
        } else if (data instanceof FormData) {
          throw '"FormData"类型的数据无法以"application/x-www-form-urlencoded"的ContentType发送';
        } else if (typeof data == "object") {
          return qs.stringify(data);
        }
      } else {
        if (data instanceof FormData) {
          return data;
        } else if (typeof data == "object") {
          return JSON.stringify(data);
        }
      }
      return data;
    },
  ],
};

const commonRequestInterceptor = (config: InternalAxiosRequestConfig) => {
  // 是否需要设置 token
  const isToken = config.headers?.isToken === false;
  const token = getToken();
  if (token && !isToken && !config.headers?.Authorization) {
    config.headers["Authorization"] = "Bearer " + token; // 让每个请求携带自定义token 请根据实际情况自行修改
  }

  if (config.method === "get" && config.params) {
    let url = config.url + "?" + toUrlParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }

  return config;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const commonRequestErrorInterceptor = (error: any) => {
  console.error(error);
  Promise.reject(error);
};

const commonResponseInterceptor = (res: AxiosResponse) => {
  if (
    res.request.responseType === "blob" ||
    res.request.responseType === "arraybuffer"
  ) {
    return res;
  } else {
    // 未设置状态码则默认成功状态
    const code = res.data.code || 0;
    if (code === 1) {
      const msg = res.data.msg;
      return Promise.reject(new Error(msg));
    } else {
      return res.data;
    }
  }
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const promptResponseErrorMessage = (error: any, defaultMsg: string) => {
  const {
    message,
    response,
  }: {
    message?: string;
    response?: AxiosResponse;
  } = error;
  let msg;
  if (response?.status == 401) {
    reloginPrompt();
    return Promise.reject("无效的会话，或者会话已过期，请重新登录。");
  } else if (response?.status == 403) {
    msg = response?.data?.message || "无权限";
  } else {
    msg = response?.data?.message || response?.data?.msg || defaultMsg;
  }

  if (msg) {
    // 简化后端未处理的异常信息
    if (msg.length > 50) {
      if (message == "Network Error") {
        msg = "后端接口连接异常";
      } else if (message && message.includes("timeout")) {
        msg = "系统接口请求超时";
      } else if (
        message &&
        message.includes("Request failed with status code")
      ) {
        msg = "系统接口" + message.substr(message.length - 3) + "异常";
      }
    }
  } else {
    msg = defaultMsg;
  }

  showNotify({ type: "danger", message: msg, duration: 5000 });
};

const reloginPrompt = () => {
  if (!reloginPrompted) {
    reloginPrompted = true;
    showConfirmDialog({
      title: "系统提示",
      message: "登录状态已过期，您可以继续留在该页面，或者重新登录",
      confirmButtonText: "重新登录",
    })
      .then(() => {
        // on confirm
        reloginPrompted = false;

        removeToken();
        location.href = "/";
      })
      .catch(() => {
        // on cancel
        reloginPrompted = false;
      });

    return Promise.reject("无效的会话，或者会话已过期，请重新登录。");
  }
};

// 创建axios实例
export const commonAxios = axios.create(commonConfig);
export const actionAxios = axios.create(commonConfig);
export const listAxios = axios.create(commonConfig);

// request拦截器
commonAxios.interceptors.request.use(
  commonRequestInterceptor,
  commonRequestErrorInterceptor
);
actionAxios.interceptors.request.use(
  commonRequestInterceptor,
  commonRequestErrorInterceptor
);
listAxios.interceptors.request.use(
  commonRequestInterceptor,
  commonRequestErrorInterceptor
);

//response拦截器
commonAxios.interceptors.response.use(commonResponseInterceptor, (error) => {
  const { response }: { response: AxiosResponse } = error;
  if (response?.status == 401) {
    reloginPrompt();
    return Promise.reject("无效的会话，或者会话已过期，请重新登录。");
  }
  return Promise.reject(error.response?.data);
});

actionAxios.interceptors.response.use(commonResponseInterceptor, (error) => {
  promptResponseErrorMessage(error, "操作失败");
  return Promise.reject(error.response?.data);
});

listAxios.interceptors.response.use(
  (res) => {
    if (
      res.request.responseType === "blob" ||
      res.request.responseType === "arraybuffer"
    ) {
      return Promise.reject(
        new Error("表格不能处理的类型：" + res.request.responseType)
      );
    } else {
      // 未设置状态码则默认成功状态
      const code = res.data.code || 0;
      if (code === 1) {
        const msg = res.data.msg;
        return Promise.reject(new Error(msg));
      } else {
        return res.data;
      }
    }
  },
  (error) => {
    promptResponseErrorMessage(error, "查询失败");
    return Promise.reject(error.response?.data);
  }
);

export default commonAxios;
